/**
 * Copyright 2011 AJG van Schie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.googlecode.julius.data.define;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import julius.utilities.CollectionHelper;

import org.joda.time.LocalDate;

import com.googlecode.julius.data.Status;
import com.googlecode.julius.utils.DateHelper;

public class DefineIssue {
    private final Integer issue_id;
    private final String status;
    private final String summary;

    private final Double est_hours;

    private final List<DefineLog> log = new ArrayList<DefineLog>();

    private final String created;

    public DefineIssue(final List<String> ticket) {
        // created|estimatedhours|totalhours|remaininghours|status|summary
        this.issue_id = (Integer.parseInt(ticket.get(0)));
        this.created = (ticket.get(1));
        this.est_hours = (Double.parseDouble(ticket.get(2)));
        // this.actual_hours = (Double.parseDouble(ticket.get(3)));
        this.status = ticket.get(5);
        this.summary = ticket.get(6);
    }

    public LocalDate getCreateDate() {
        return DateHelper.parseToDate(created);
    }

    public Map<LocalDate, Status> getStatusOverviewUpTo(final LocalDate endDate) {
        Map<LocalDate, Status> sparse = getStatusOverviewSparse();
        Map<LocalDate, Status> full = new HashMap<LocalDate, Status>(sparse);
        LocalDate cursor = getCreateDate();
        Status current = sparse.get(cursor);
        while (!cursor.isAfter(endDate)) {
            if (!sparse.containsKey(cursor)) {
                full.put(cursor, current);
            } else {
                current = sparse.get(cursor);
            }
            cursor = cursor.plusDays(1);
        }
        return full;
    }

    // return map with for each date the initial state, and changed states (but ommitting days on which nothing changed)
    public Map<LocalDate, Status> getStatusOverviewSparse() {

        Map<LocalDate, Status> hourshistory = CollectionHelper.map();

        hourshistory.put(getCreateDate(), Status.New);

        for (DefineLog logi : log) {

            if (logi.isStatusChange()) {

                Status val = hourshistory.get(logi.getDate());

                Status newVal = Status.findByName(logi.getNewValue());

                if (val == null || !val.getAllBefore().contains(newVal)) {

                    hourshistory.put(logi.getDate(), newVal);

                }

            }

        }

        return hourshistory;

    }

    // TODO BUG: dag met initieel remaining hours 0, maar wel estimated hours rekent altijd met estimated ipv remaingin

    public Map<LocalDate, Double> getHourOverviewUpTo(final LocalDate startDate, final LocalDate endDate) {
        Map<LocalDate, Double> sparse = getHourOverviewSparse(startDate);
        Map<LocalDate, Double> full = new HashMap<LocalDate, Double>(sparse);
        LocalDate cursor = getCreateDate();
        Double current = sparse.get(cursor);
        while (!cursor.isAfter(endDate)) {
            if (!sparse.containsKey(cursor)) {
                full.put(cursor, current);
            } else {
                current = sparse.get(cursor);
            }
            cursor = cursor.plusDays(1);
        }
        return full;
    }

    // return map with for each date the initial size, and changed sizes (but ommitting days on which nothing changed)
    public Map<LocalDate, Double> getHourOverviewSparse(final LocalDate periodStart) {
        Map<LocalDate, Double> hourshistory = CollectionHelper.map();
        hourshistory.put(getCreateDate(), getEstHoursAtCreation(periodStart));
        for (DefineLog logi : log) {
            if (logi.isRemainingHoursChange()) {
                if (!logi.hasNewValue()) {
                    Double val = hourshistory.get(logi.getDate());
                    Double newVal = Double.valueOf(logi.getNewValue());
                    if (val == null || val > newVal) {
                        hourshistory.put(logi.getDate(), newVal);
                    }
                } else {
                    hourshistory.put(logi.getDate(), 0d);
                }
            }
        }
        return hourshistory;

    }

    public Double getEstHoursAtCreation(final LocalDate periodStart) {
        LocalDate d = new LocalDate();
        Double hours = getEst_hours();
        for (DefineLog logi : log) {
            if (logi.isEstimatedHoursChange()) {
                if (!(logi.getOldValue().trim().equals("") || logi.getOldValue().trim().equals("0"))) {
                    if (logi.getDate().isBefore(d) && logi.getDate().isAfter(periodStart)) {
                        d = logi.getDate();
                        hours = Double.valueOf(logi.getOldValue().trim());
                    }
                }
            }
        }
        return hours;
    }

    public void addLog(final DefineLog defineLog) {
        log.add(defineLog);
    }

    private Status getStatus() {
        return Status.findByName(status);
    }

    private Double getEst_hours() {
        if (est_hours == null) {
            return 0d;
        }
        return est_hours;
    }

    @Override
    public String toString() {
        return "" + issue_id + "  " + getStatus() + " - " + summary + "";
    }

}
